<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自动老练</title>
</head>
<center>

<body>
    <style>
        h4 {color:red;}
        p {text-align: center;}
        
        #left_start {
            background-color: red;
            position: relative; 
            /* float: left;  */
            display: inline-block;
            /* display: table; */
            width: 20%;
            height: 100%;
            align-items: center;
            
        }

        #middle_process {
            background-color: aqua; 
            position: relative; 
            /* float: left; */
            display: inline-block;
            width: 50%;
            height: 100%;
        }

        #right_end {
            background-color: yellow; 
            /* float: left; */
            display: inline-block;
            width: 21%;
            height: 100%;
        }

        #up_arrow {
            background-color: darkorange;
        }

        #record {
            background-color: deepskyblue;
        }
        .center_block {background-color: green; display: inline-block; width: 32%;}
        .down_block {background-color: gold; display: inline-block; width: 32%;}
        .config_input {width: 30%;}
    </style>

    <div>

        <h4>请先选择通信端口</h4>
        <p>刷新页面会自动关闭通信端口</p>
        <button id="com_chooser">选择通信端口</button>
        <input type="text" id="com_product_id" readonly="readonly" placeholder="product id将会显示">
        <input type="text" id="com_vendor_id" readonly="readonly" placeholder="vendor id将会显示">
        <button id="port_closer" disabled="true" onclick="try_to_close_port()">关闭端口</button>
        <br>
    </div>

    <div id="left_start">
        <p>准备开始</p>
        <button onclick="start_aging();">开始老练</button>
        <button onclick="stop_in_emergency();">紧急停止</button>
        
    </div>

    <div id="middle_process">
        <div id="up_arrow">
            <p>up</p>
            <span>
                需要执行
                <input type="number" class="config_input" id="up_wanted_time" value="5">次，                
                而当前已经完成<span id="up_current_done_time">0</span>次
                <br>

            </span>
        </div>

        <div id="center_states">
            <p>center</p>
            <div class="center_block" id="c1">
                <p>升压</p>
                <span>
                    升压速率
                    <input type="number" class="config_input" id="c1_increase_rate" value="4">伏特/秒
                    <br>
                    升压目标
                    <input type="number" class="config_input" id="c1_target_volt" value="100">伏特
                    <br>
                </span>
            </div>
            <div class="center_block" id="c2">
                <p>维持考验</p>
                <span>
                    维持时间
                    <input type="number" class="config_input" id="c2_keep_time" value="0.05">分钟
                    <br>
                </span>
            </div>
            <div class="center_block" id="c3">
                <p>降到起点</p>
                <span>
                    降压速率
                    <input type="number" class="config_input" id="c3_decrease_rate" value="3">伏特/秒
                    <br>
                </span>
            </div>
            
        </div>

        <div id="down_pause">
            <p>要是打火了就会对应进入下面的小黑屋！</p>
            <div class="down_block" id="d1">
                <span>
                    降压大小
                    <input type="number" class="config_input" id="d1_volt" value="1">伏特
                    <br>
                    维持时间
                    <input type="number" class="config_input" id="d1_time" value="0.5">分钟
                    <br>
                </span>
                <p>
                    降压宽容
                </p>
            </div>
            <div class="down_block" id="d2">
                <span>
                    降压大小
                    <input type="number" class="config_input" id="d2_volt" value="2">伏特
                    <br>
                    维持时间
                    <input type="number" class="config_input" id="d2_time" value="0.5">分钟
                    <br>
                </span>
                <p>
                    降压小黑屋
                </p>
            </div>
            <div class="down_block" id="d3">

            </div>
        </div>
    </div>

    <div id="right_end">
        <p>结束了</p>
    </div>
    <div id="current_parameters">
        <span>当前四个通道的电压：<span id="current_volt">不知道多少</span>V</span>
        <span>当前总共打火次数：<span id="current_discharge_num">不知道多少</span>次</span>
        
    </div>
    <div id="record">
        打火记录
    </div>
    <div id="debug">
        <button onclick="get_voltage(1);">get_voltage</button>
        <button onclick="get_discharge_num();">get_discharge_num</button>
        <button onclick="set_slew_rate(1,1);">set_slew_rate</button>
        <button onclick="set_target_voltage(1,0);">set_target_voltage</button>
        <br>
        <input type="number" placeholder="你想现在多少伏" id="create_volt">
        <button onclick="generate_voltage_reply();">产生回复电压数据</button>
        <input type="number" placeholder="你想放电几次" class="config_input" id="create_num">
        <button onclick="generate_discharge_num();">产生放电数据</button>
        <!-- <button onclick="create_send_u8_arr(default_send_info);">create_debug_string</button> -->
    </div>

    <script>
        "use strict"

        // class HV_comunicator {

        // }
        // 重点实现的功能
        const CMD_SET_HV_OUT_TAR_VAL = 12061;   // send: int hv_ch, float val
        const CMD_SET_HV_OUT_SLEW_RATE = 12063; // send: int hv_ch, float slew_rate
        // const CMD_GET_IP_VAL = 12012;
        const CMS_GET_HV_SAMPLE_VOL_VAL = 12090;    // send: int hv_ch, rec: int hv_ch, float val
        const CMD_GET_DISCHARGE_NUM = 12013;        // send: none, rec: int num

        const ADDRESS_ALL = 0x0041;

        const DEFAULT_DECREASING_RATE = 1000;

        // const 好 = {
        //     降压小黑屋 : 2
        // }

        // console.log(好.降压小黑屋);
        
        // 向高压箱发送的数据
        const default_send_info = {
            Address : ADDRESS_ALL,   // 2 bytes, a number
            Command : CMS_GET_HV_SAMPLE_VOL_VAL,        // 2 bytes, a number
            Pack_id : 100,        // 4 bytes, a number
            Data_field : 0,     // 16 bytes, user created, a uint8 array
            Reserved : 0,       // 4 bytes nothing
            Checksum : 0        // 1 byte, auto created
        }
        // default_send_info.Data_field = new Uint8Array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17]);


        default_send_info.Data_field = concatenate(Uint8Array,new Uint8Array([1,0,0,0]),
                convertTypedArray(new Float32Array([1.33])),new Uint8Array(8));
        // [1,0,0,0,0xf5,0xa8,0xf4,0x42,0,0,0,0,0,0,0,0];

        const rec_info = {
            Address : 0,   // 2 bytes, a number
            Command : 0,        // 2 bytes, a number
            Pack_id : 0,        // 4 bytes, a number
            Data_field : 0,     // 16 bytes, user created, a uint8 array
            ErrorCode : 0,      // 2 bytes, a number
            RespTime : 0,       // 2 bytes, a number
            Checksum : 0        // 1 byte, auto created
        }

        // 改变数组的底层类型，保持字节相同 https://www.coder.work/article/3821011
        // 还是C语言更擅长这些操作
        function convertTypedArray(src, type = Uint8Array) {
            var buffer = new ArrayBuffer(src.byteLength);
            var baseView = new src.constructor(buffer).set(src);
            let arr = new type(buffer);
            return arr;
        }

        // https://www.asciim.cn/hex/float.html

        // 拼接多个数组
        function concatenate(resultConstructor, ...arrays) {
            let totalLength = 0;
            for (let arr of arrays) {
                totalLength += arr.length;
            }
            let result = new resultConstructor(totalLength);
            let offset = 0;
            for (let arr of arrays) {
                result.set(arr, offset);
                offset += arr.length;
            }
            return result;
        }

        // 从待发送的数据对象生成uint8序列
        function create_send_u8_arr(send_info) {
            var result_buf;
            var data_sum;
            if(send_info.Data_field.length != 16) {
                alert("data field length not right!");
                return [0];
            }
            result_buf = concatenate(Uint8Array,
                convertTypedArray(new Uint16Array([send_info.Address])),
                convertTypedArray(new Uint16Array([send_info.Command])),
                convertTypedArray(new Uint32Array([send_info.Pack_id])),
                send_info.Data_field,
                convertTypedArray(new Uint32Array([send_info.Reserved])),
                );
            data_sum = 0;
            for(let i =0;i<28;i++) {
                data_sum += result_buf[i];
            }
            result_buf = concatenate(Uint8Array,result_buf,new Uint8Array([data_sum & 0xFF]));
            
            
            return result_buf;
        }
        
        
        let asd = create_send_u8_arr(default_send_info);
        console.log(asd);

        function analyse_data_receive(arr) {
            var data_sum;
            data_sum = 0;
            for(let i =0;i<28;i++) {
                data_sum += arr[i];
            }
            if(arr[28]!=(data_sum & 0xFF)) {
                console.log("Receive error!");
                return null;
            }
            rec_info.Address = convertTypedArray(arr.subarray(0,2),Uint16Array)[0];
            rec_info.Command = convertTypedArray(arr.subarray(2,4),Uint16Array)[0];
            rec_info.Pack_id = convertTypedArray(arr.subarray(4,8),Uint32Array)[0];
            rec_info.Data_field = arr.subarray(8,24);
            rec_info.ErrorCode = convertTypedArray(arr.subarray(24,26),Uint16Array)[0];
            rec_info.RespTime = convertTypedArray(arr.subarray(26,28),Uint16Array)[0];
            rec_info.Checksum = convertTypedArray(arr.subarray(28,29),Uint8Array)[0];
            return rec_info;
        }
        // console.log(analyse_data_receive(create_send_u8_arr(default_send_info)));

        // 串口
        // 检测浏览器是否支持串口
        if(!("serial" in navigator))
        {
            alert("你的浏览器不支持串口，请用最新版的Chrome或Edge浏览器打开");
        }
        
        // 给端口选择按钮增加点击响应函数
        const com_chooser_button = document.querySelector('#com_chooser');
        var port;   // 端口
        var writer; // 写端口
        var reader;
        let keepReading = true;

        // 把最新的数据放在这里
        var current_voltage = [0,0,0,0];
        var old_discharge_num = 0, new_discharge_num = 0, initialized = 0, sparked_just_now,
            software_discharge_num = 0;


        // 为端口选择按钮增加点击异步响应函数
        com_chooser_button.addEventListener('click', async function() {
            // Prompt user to select any serial port.
            port = await navigator.serial.requestPort();
            if(port != null)
            {
                // Wait for the serial port to open.
                await port.open({ baudRate: 9600 });
                console.log("Open",port,"at baud rate 9600!");
                const {usbProductId, usbVendorId} = port.getInfo();
                console.log("Product id: ",usbProductId,"vendor id: ",usbVendorId);
                document.getElementById("com_product_id").value = usbProductId;
                document.getElementById("com_vendor_id").value = usbVendorId;
                writer = port.writable.getWriter();
                document.getElementById("port_closer").disabled = false;
                // reader = port.readable.getReader();
                // 持续读取

                // 开启电压值更新
                setInterval(() => {
                    document.getElementById("current_volt").innerHTML = current_voltage;
                    document.getElementById("current_discharge_num").innerHTML = software_discharge_num;
                    setTimeout(() => {
                        get_voltage(1);
                        
                    }, 0);
                    setTimeout(() => {
                        get_discharge_num();
                        
                    }, 100);

                }, 1000);

                while(port.readable && keepReading) {
                    reader = port.readable.getReader();
                    try {
                        while(true) {
                            const {value,done} = await reader.read();
                            if(done) {
                                reader.releaseLock();
                                break;
                            }
                            if(value) {
                                console.log("电脑接收到了数据")
                                console.log(value);
                                var rec_data = analyse_data_receive(value);
                                if(rec_data.Address == ADDRESS_ALL) {
                                    // console.log("here");
                                    switch (rec_data.Command) {
                                        case CMS_GET_HV_SAMPLE_VOL_VAL:
                                            console.log("电脑收到了高压箱返回的电压数据")
                                            // console.log("at getting sample voltage");
                                            // channel 取值为1~4，数组序号还要减1
                                            current_voltage[convertTypedArray(rec_data.Data_field.subarray(0,4),Uint32Array)[0] - 1] = convertTypedArray(rec_data.Data_field.subarray(4,8),Float32Array)[0];
                                            break;
                                        case CMD_GET_DISCHARGE_NUM:
                                            console.log("电脑收到了高压箱返回的放电数据")
                                            new_discharge_num = convertTypedArray(rec_data.Data_field.subarray(0,4),Uint32Array)[0];
                                            if(!initialized) {
                                                initialized = 1;
                                                software_discharge_num = 0;
                                                old_discharge_num = new_discharge_num;

                                            }
                                            else {
                                                if(old_discharge_num != new_discharge_num) {
                                                    sparked_just_now = true;
                                                    software_discharge_num +=1;
                                                    old_discharge_num = new_discharge_num;
                                                }
                                            }
                                            break;
                                        default:
                                            console.log("unexpected command");
                                            break;
                                    }
                                }
                            }
                        }
                    } catch (error) {
                        console.log("An error occurred at reading");
                    } finally {
                        reader.releaseLock();
                    }
                }
            }
        });

        // 端口关闭函数
        async function try_to_close_port(){
            writer.releaseLock();
            reader.releaseLock();
            await port.close();
            document.getElementById("port_closer").disabled = true;
            document.getElementById("com_product_id").value = "";
            document.getElementById("com_vendor_id").value = "";
        }

        async function get_voltage(channel) {
            var send_info = {
                Address : 0x0041,   // 2 bytes, a number
                Command : CMS_GET_HV_SAMPLE_VOL_VAL,        // 2 bytes, a number
                Pack_id : 0,        // 4 bytes, a number
                Data_field : 0,     // 16 bytes, user created, a uint8 array
                Reserved : 0,       // 4 bytes nothing
                Checksum : 0        // 1 byte, auto created
            }
            send_info.Data_field = concatenate(Uint8Array,
                convertTypedArray(new Uint32Array([channel])),
                new Uint8Array(12)
            );
            await writer.write(create_send_u8_arr(send_info));
            // const {value,done} = await reader.read();
            // if(done) {
            //     reader.releaseLock();
            // }
            // if(value) {
            //     console.log(value);
            //     var rec_data = analyse_data_receive(value);

            // }
        }
        async function get_voltage(channel) {
            var send_info = {
                Address : 0x0041,   // 2 bytes, a number
                Command : CMS_GET_HV_SAMPLE_VOL_VAL,        // 2 bytes, a number
                Pack_id : 0,        // 4 bytes, a number
                Data_field : 0,     // 16 bytes, user created, a uint8 array
                Reserved : 0,       // 4 bytes nothing
                Checksum : 0        // 1 byte, auto created
            }
            send_info.Data_field = concatenate(Uint8Array,
                convertTypedArray(new Uint32Array([channel])),
                new Uint8Array(12)
            );
            await writer.write(create_send_u8_arr(send_info));
            // const {value,done} = await reader.read();
            // if(done) {
            //     reader.releaseLock();
            // }
            // if(value) {
            //     console.log(value);
            //     var rec_data = analyse_data_receive(value);

            // }
        }
        async function get_discharge_num() {
            var send_info = {
                Address : 0x0041,   // 2 bytes, a number
                Command : CMD_GET_DISCHARGE_NUM,        // 2 bytes, a number
                Pack_id : 0,        // 4 bytes, a number
                Data_field : 0,     // 16 bytes, user created, a uint8 array
                Reserved : 0,       // 4 bytes nothing
                Checksum : 0        // 1 byte, auto created
            }
            send_info.Data_field = new Uint8Array(16);
            await writer.write(create_send_u8_arr(send_info));
            // const {value,done} = await reader.read();
            // if(done) {
            //     reader.releaseLock();
            // }
            // if(value) {
            //     console.log(value);
            //     var rec_data = analyse_data_receive(value);

            // }
        }
        async function set_target_voltage(channel,voltage) {
            var send_info = {
                Address : 0x0041,   // 2 bytes, a number
                Command : CMD_SET_HV_OUT_TAR_VAL,        // 2 bytes, a number
                Pack_id : 0,        // 4 bytes, a number
                Data_field : 0,     // 16 bytes, user created, a uint8 array
                Reserved : 0,       // 4 bytes nothing
                Checksum : 0        // 1 byte, auto created
            }
            send_info.Data_field = concatenate(Uint8Array,
                convertTypedArray(new Uint32Array([channel])),
                convertTypedArray(new Float32Array([voltage])),
                new Uint8Array(8)
            );
            await writer.write(create_send_u8_arr(send_info));
        }
        async function set_slew_rate(channel,slew_rate) {
            var send_info = {
                Address : 0x0041,   // 2 bytes, a number
                Command : CMD_SET_HV_OUT_SLEW_RATE,        // 2 bytes, a number
                Pack_id : 0,        // 4 bytes, a number
                Data_field : 0,     // 16 bytes, user created, a uint8 array
                Reserved : 0,       // 4 bytes nothing
                Checksum : 0        // 1 byte, auto created
            }
            send_info.Data_field = concatenate(Uint8Array,
                convertTypedArray(new Uint32Array([channel])),
                convertTypedArray(new Float32Array([slew_rate])),
                new Uint8Array(8)
            );
            await writer.write(create_send_u8_arr(send_info));
        }


        // 状态机模型
        // const 准备开始  = 0;
        // const 升压      = 1;
        // const 维持考验  = 2;
        // const 降到起点  = 3;
        // const 结束了    = 4;
        // const 降压宽容  = 5;
        // const 降压小黑屋 = 6;

        // const Singal_buffer = {
        //     user_start : 0,
        // };

        // function param_are_OK() {
        //     alert("parameter wrong!");
        //     return false;
        // }

        // var next_state = 0, current_state = 0;
        // setInterval(() => {
        //     // 计算所需状态
        //     switch (current_state) {
        //         case 准备开始:
        //             if(Singal_buffer.user_start) {
        //                 Singal_buffer.user_start = 0;
        //                 next_state = 升压;
        //             }
        //             break;
                
        //         case 升压:
                    
        //             break;
        //         case 维持考验:
                    
        //             break;
        //         case 降到起点:
                    
        //             break;
        //         case 结束了:
                    
        //             break;
        //         case 降压宽容:
                    
        //             break;
        //         case 降压小黑屋:
                    
        //             break;

        //         default:
        //             alert("状态错误")
        //             break;
        //     }

        //     // 根据当前状态和应该的下一状态计算应发送的控制消息


        //     // 状态更新
        //     next_state = current_state;
        // }, 1000);

        
        // console.log(document.getElementById("c1").style.border) ;
        
        // 框住当前状态
        function cover_red_box(id) {
            document.getElementById(id).style.border = "5px solid red";
        }
        function clear_red_box(id) {
            document.getElementById(id).style.border = "";
        }
        function only_red_box(id) {
            clear_red_box("c1");
            clear_red_box("c2");
            clear_red_box("c3");
            clear_red_box("d1");
            clear_red_box("d2");
            clear_red_box("right_end");
            cover_red_box(id);
        }
        
        // cover_red_box("c1");
        // clear_red_box("c1");
        
        function generate_voltage_reply() {
            default_send_info.Command = CMS_GET_HV_SAMPLE_VOL_VAL;
            default_send_info.Data_field = concatenate(Uint8Array,new Uint8Array([1,0,0,0]),
                convertTypedArray(new Float32Array([Number(document.getElementById("create_volt").value)])),new Uint8Array(8));
            var org = create_send_u8_arr(default_send_info);
            var str = "";
            for(let i = 0;i<29;i++) {
                str += (org[i].toString(16) + " ");
            }
            console.log(str);
        }
        function generate_discharge_num() {
            default_send_info.Command = CMD_GET_DISCHARGE_NUM;
            default_send_info.Data_field = concatenate(Uint8Array,
                convertTypedArray(new Uint32Array([Number(document.getElementById("create_num").value)])),new Uint8Array(12));
            var org = create_send_u8_arr(default_send_info);
            var str = "";
            for(let i = 0;i<29;i++) {
                str += (org[i].toString(16) + " ");
            }
            console.log(str);
        }

        var volt_increasing_timer = null;
        var first_tolerance_timer = null;
        var first_tolerance_return_timer = null;

        // 由发起者协调所有资源
        function start_aging() {
            only_red_box("c1");
            console.log("start aging!");
            first_tolerance_timer = setInterval(() => {
                if(sparked_just_now) {
                    console.log("now spark at the first place");
                    sparked_just_now = false;
                    continuous_send_increasing();
                    only_red_box("d1");
                    // 将在一段时间后返回

                    // 首先清除原来的timer
                    if(first_tolerance_return_timer != null) {
                        clearTimeout(first_tolerance_timer);
                        first_tolerance_timer = null;
                    }

                    first_tolerance_return_timer = setTimeout(() => {
                        setTimeout(() => {
                            set_target_voltage(1,getNumberOfId("c1_target_volt"));
                            
                        }, 0);
                        setTimeout(() => {
                            set_slew_rate(1,getNumberOfId("c1_increase_rate"));
                            
                        }, 100);
                        only_red_box("c1");
                    }, getNumberOfId("d1_time") * 60 * 1000);
                }
            }, 500);

            setTimeout(() => {
                set_slew_rate(1,Number(document.getElementById("c1_increase_rate").value));
            }, 0);
            setTimeout(() => {
                set_target_voltage(1,Number(document.getElementById("c1_target_volt").value));
            }, 100);

            // checker at 升压状态。包含状态转移的方法
            if(volt_increasing_timer != null) {
                clearInterval(volt_increasing_timer)
                volt_increasing_timer = null;
            }

            
            // 这样驱动，深度会越来越大
            volt_increasing_timer = setInterval(() => {
                if(current_voltage[0] >= Number(document.getElementById("c1_target_volt").value)) {
                    // alert("yes, it is bigger");
                    clearInterval(volt_increasing_timer);
                    volt_increasing_timer = null;
                    // 进入维持考验的状态
                    get_into_stable();
                }
            }, 500);

        }

        var second_decrease_small_black_house_timer = null;
        var second_decrease_small_black_house_return_timer = null;
        // 第二个小黑屋

        function getNumberOfId(id) {
            return Number(document.getElementById(id).value);
        }

        function get_into_stable() {
            console.log("get into stable");
            only_red_box("c2");
            second_decrease_small_black_house_timer = setInterval(() => {
                if(sparked_just_now) {
                    only_red_box("d2")
                    sparked_just_now = false;
                    setTimeout(() => {
                        set_target_voltage(1,current_voltage[0] - getNumberOfId("d2_volt"));
                        
                    }, 0);
                    setTimeout(() => {
                        set_slew_rate(1,DEFAULT_DECREASING_RATE);
                        
                    }, 100);
                    clearInterval(second_decrease_small_black_house_timer);
                    
                    // 将在一段时间后返回

                    // 首先清除原来的timer
                    if(second_decrease_small_black_house_return_timer != null) {
                        clearTimeout(second_decrease_small_black_house_return_timer);
                        second_decrease_small_black_house_return_timer = null;
                    }

                    second_decrease_small_black_house_return_timer = setTimeout(() => {
                        setTimeout(() => {
                            set_target_voltage(1,getNumberOfId("c1_target_volt"));
                        }, 0);
                        setTimeout(() => {
                            set_slew_rate(1,getNumberOfId("c1_increase_rate"));
                        }, 100);
                        only_red_box("c2");
                    }, getNumberOfId("d2_time") * 60 * 1000);
                }
            }, 500);

            setTimeout(() => {

                if(second_decrease_small_black_house_timer != null)
                    clearInterval(second_decrease_small_black_house_timer);
                second_decrease_small_black_house_timer = null;
                if(second_decrease_small_black_house_return_timer != null);
                    clearTimeout(second_decrease_small_black_house_return_timer);
                second_decrease_small_black_house_return_timer = null;
                get_into_decrease();
            }, Number(document.getElementById("c2_keep_time").value) * 60 * 1000);
        }
        // 降到起点
        
        // 或许可以靠定时发送，一定程度上解决发送出错的问题
        
        var decrease_timer = null;
        
        function get_into_decrease() {
            only_red_box("c3");
            setTimeout(() => {
                set_target_voltage(1,0);
            }, 0);
            setTimeout(() => {
                set_slew_rate(1,Number(document.getElementById("c3_decrease_rate").value));
            }, 100);
            decrease_timer = setInterval(() => {
                // 电压降到0左右
                if(current_voltage[0] <= 0) {
                    // 结束了
                    clearInterval(decrease_timer);
                    decrease_timer = null;
                    current_done_times +=1;
                    document.getElementById("up_current_done_time").innerHTML = current_done_times;
                    wanted_times = Number(document.getElementById("up_wanted_time").value);
                    if(current_done_times >= wanted_times) {
                        // stop
                        console.log("搞定咯！");
                        only_red_box("right_end");
                    }
                    else {
                        setTimeout(() => {
                            start_aging();  
                        }, 200);
                    }
                }
            }, 1000);
        }
        var wanted_times = 1,current_done_times = 0;
        
        var continuous_send_increasing_timer = null;
        function continuous_send_increasing() {
            if(continuous_send_increasing_timer != null)
                clearInterval(continuous_send_increasing_timer);
            continuous_send_increasing_timer = setInterval(() => {
                
            }, 1000);
        }
        function clear_send_increasing() {
            if(continuous_send_increasing_timer != null) {
                clearInterval(continuous_send_increasing_timer);
                continuous_send_increasing_timer = null;
            }
        }

    </script>
</body>
    
</center>
</html>